import { fetchResource } from '../utils/fetchResource'

import { sandBox } from '../sandbox'

// 记载html的方法
export const loadHtml = async app => {
  // 子应用需要显示在哪里
  const container = app.container
  // 应用的入口
  const entry = app.entry
  const [dom, scripts] = await parseHtml(entry, app.name)
  const el = document.querySelector(container)
  if (!el) {
    throw new Error('容器不存在')
  }
  el.innerHTML = dom
  scripts.forEach(script => sandBox(app, script))

  return app
}

// 根据子应用的name来做缓存
const cache = {}

export const parseHtml = async (entry, name) => {
  if (cache[name]) {
    return cache[name]
  }
  const html = await fetchResource(entry)
  const div = document.createElement('div')
  div.innerHTML = html

  // 还得处理 标签、link、script(src、js)
  let [dom, scriptUrl, script] = await getResources(div, entry)
  const fetchScripts = await Promise.all(scriptUrl.map(async url => await fetchResource(url)))
  script = script.concat(fetchScripts)

  cache[name] = [dom, script]

  return [dom, script]
}

export const getResources = async (root, entry) => {
  const scriptUrl = []
  const script = []
  const dom = root.outerHTML

  // 深度解析
  function deepParse(element) {
    const children = element.children
    const parent = element.parent

    // 第一步 处理位于script中的内容
    if (element.nodeName.toLowerCase() === 'script') {
      const src = element.getAttribute('src')
      if (!src) {
        script.push(element.outerHTML)
      } else {
        if (src.startsWith('http')) {
          scriptUrl.push(src)
        } else {
          // 请求的页面的资源地址可能是以根目录地址为资源地址
          scriptUrl.push(`http:${entry}/src`)
        }
      }
      if (parent) {
        // 替换节点
        const newChild = document.createComment('此js文件已经被微前端替换') // 注释节点
        parent.replaceChild(newChild, element)
      }
    }

    // link
    if (element.nodeName.toLowerCase() === 'link') {
      const src = element.getAttribute('href')
      if (src.endsWith('.js')) {
        if (src.startsWith('http')) {
          scriptUrl.push(src)
        } else {
          scriptUrl.push(`http:${entry}/src`)
        }
      }
    }

    for (let i = 0; i < children.length; i++) {
      deepParse(children[i])
    }
  }

  deepParse(root)

  return [dom, scriptUrl, script]
}
